package com.navi.loaddata.loadService.impl.measureData;

import com.navi.loaddata.core.errorLog.ErrorCode;
import com.navi.loaddata.core.etlException.ETLException2;
import com.navi.loaddata.core.gpEntity.*;
import com.navi.loaddata.core.mysqlEntity.EdaMeasureDefecttypeD;
import com.navi.loaddata.core.mysqlEntity.EtlConfD;
import com.navi.loaddata.core.mysqlEntity.EtlConfDModel;
import com.navi.loaddata.core.oracleEntity.*;
import com.navi.loaddata.core.util.CorrdTransformException;
import com.navi.loaddata.core.util.LoggerUtil;
import com.navi.loaddata.loadDao.SaveBaseDataDao;
import com.navi.loaddata.loadDao.SaveFileDataDao;
import com.navi.loaddata.loadService.impl.baseData.LoadMesBaseDataService;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.navi.loaddata.core.constant.GenericDef.SHOP_OC;
import static java.util.stream.Collectors.groupingBy;

/**
 * @author xufan
 */
@Service
//@Transactional(transactionManager = "thirdaryPlatformTransactionManager",
//        rollbackFor = {RuntimeException.class, Exception.class})
public class LoadMeasureDataService15 {
    private static final Logger logger = LoggerFactory.getLogger(LoadMeasureDataService15.class);
    private LoggerUtil loggerUtil = new LoggerUtil(this.getClass());

    @Autowired
    private LoadMesBaseDataService loadMesBaseDataService;
    @Autowired
    private ProcessDefectDataService processDefectDataService;
    @Autowired
    private LoadDefectInfoService loadDefectInfoService;
    @Autowired
    private SaveBaseDataDao saveBaseDataDao;
    @Autowired
    private SaveFileDataDao saveFileDataDao;
//    @Autowired
//    private LoadTtpResultService loadTtpResultService;

    public String[] loadMeasureDataMain(EtlConfDModel etlConfD) throws Exception {
        String[] resMsg = loadMeasureData(etlConfD);
        String msg = etlConfD.getOpe();
        if (StringUtils.isEmpty(etlConfD.getOpe())) msg = "ALL";
        logger.info("OpeId={} LoadMeasureDataMain finish!", msg);
        return resMsg;
    }

    /**
     * Load Measure Data
     * <p>
     * load base -> session table
     * load defect data  -> session table
     * call base proc  -> auto commit
     * call defect proc -> no auto commit
     * delete defect session table
     *
     * @param etlConfD
     */
    private String[] loadMeasureData(EtlConfDModel etlConfD) throws Exception {
        String[] resMsg = new String[3];
        int okCnt = 0;
        int errCnt = 0;
        String errMsg = null;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // defect glass
        List<GpGlassF> defectGlassList = loadDefectInfoService.loadGlassInfo(etlConfD);
        logger.info("{} defect glass count {}", etlConfD.getShop(), defectGlassList.size());

        if (!defectGlassList.isEmpty()) {
            int glassSize = defectGlassList.size();
            //getMap坐标，getDefectCodeType
            HashMap<String, List<MppLayoutPnlD>> layoutPnlMap = new HashMap<>();
            HashMap<String,EdaMeasureDefecttypeD> defectCodeMap = new HashMap<>();

                if ("CELL2".equals(etlConfD.getCellType())) {
                    layoutPnlMap = loadDefectInfoService.small2big(defectGlassList);
                    defectCodeMap=loadDefectInfoService.getDefectCodeTypeList(SHOP_OC);
                } else {
                    layoutPnlMap = loadDefectInfoService.big2small(defectGlassList);
                }


            // base
            List<EtlStepV> etlStepVList = loadMesBaseDataService.loadAllFinalStep(etlConfD.getShop());
            List<EtlProductV> etlProductVList = loadMesBaseDataService.loadAllFinalProduct(etlConfD.getShop());
            // save base and proc
            saveBaseDataDao.saveBaseData(etlConfD, etlStepVList, etlProductVList);

//            //param
//            if("ARRAY".equals(etlConfD.getShop())||"CF".equals(etlConfD.getShop())) {
//                List<MParamD> ParamList = loadMesBaseDataService.loadParamInfo2(etlConfD.getShop());
//                List<EtlParamV> etlParamList= processBaseDataService.processParamInfo2(ParamList);
//                saveBaseDataDao.saveParamData(etlConfD, etlParamList);
//            }

            Map<String, String> mOpeDList = loadDefectInfoService.loadMOpeDInfo(etlConfD);
            for (int i = 0; i < glassSize; i += 15) {
                List<GpGlassF> curGlassList = new ArrayList<>();
                for (int j = 0; j < 15; j++) {
                    if (i + j < glassSize) {
                        curGlassList.add(defectGlassList.get(i + j));
                    }
                }

                //panel
                Map<String, List<GpChipF>> defectPanelMap = new HashedMap();
                if (!"CELL2".equals(etlConfD.getCellType())) {//CELL2 没有chip
                    defectPanelMap = loadDefectInfoService.loadPanelInfo(etlConfD, curGlassList);
//                        logger.info("{} defect panel count {}", etlConfD.getShop(),defectPanelMap.size());
                }

                //defect
                Map<String, List<GpDefectF>> defectMap =
                        loadDefectInfoService.loadDefectInfo(etlConfD, curGlassList);

                Map<String, List<EtlGlassV>> etlGlassVMap = new HashedMap();
                Map<String, List<EtlChipV>> etlChipVMap = new HashedMap();
                Map<String, List<EtlDefectV>> etlDefectVMap = new HashMap<>();

//                Map<String,List<EtlTtpResultV>> etlTtpResultVMap=new HashedMap();

                for (GpGlassF glass : curGlassList) {
                    try {
                        etlGlassVMap.put(glass.getUnqSeqId(), processDefectDataService.processGlass(etlConfD, glass));
                        if (!"CELL2".equals(etlConfD.getCellType())) {
                            etlChipVMap.put(glass.getUnqSeqId(), processDefectDataService.processPanel(etlConfD, defectPanelMap.get(glass.getUnqSeqId())));
                        }
                        etlDefectVMap.put(glass.getUnqSeqId(), processDefectDataService.processDefect(layoutPnlMap.get(glass.getGlassId().substring(0, 10)), etlConfD, defectMap.get(glass.getUnqSeqId()), mOpeDList,defectCodeMap));
                    } catch (ETLException2 e) {
                        String glassMsg = "glassId=" + glass.getGlassId() + " opeId=" + glass.getOpeId() + " procEndTime=" + glass.getEvtTimestamp();

                        logger.error(ErrorCode.ERROR_PROCESS_GP2ORA_DEFECT_FILE.getErrorMsg() + "\n" + glassMsg + "转化失败,错误原因：" + LoggerUtil.stackTraceToString(e));
                        if (!StringUtils.isEmpty(errMsg)) {
                            errMsg = errMsg
                                    + glassMsg
                                    + "转化失败,错误原因：" + e.getErrMsg() + "。\n";
                        } else {
                            errMsg = glassMsg
                                    + "转化失败,错误原因：" + e.getErrMsg() + "。\n";
                        }
                        errCnt++;
                    }catch (CorrdTransformException e){
                        String glassMsg = "glassId=" + glass.getGlassId() + " opeId=" + glass.getOpeId() + " procEndTime=" + glass.getEvtTimestamp();

                        logger.error(ErrorCode.ERROR_PROCESS_GP2ORA_DEFECT_FILE.getErrorMsg() + "\n" + glassMsg + "转化失败,错误原因：" + e.getErrorCode());
                        if (!StringUtils.isEmpty(errMsg)) {
                            errMsg = errMsg
                                    + glassMsg
                                    + "转化失败,错误原因：" + e.getErrorCode() + "。\n";
                        } else {
                            errMsg = glassMsg
                                    + "转化失败,错误原因：" + e.getErrorCode() + "。\n";
                        }
                        errCnt++;
                    }

//                    try{
//                        loadTtpResultService.getTtpResultList(etlConfD,curGlassList);
////                        etlTtpResultVMap.put(glass.getUnqSeqId(),loadDefectInfoService.getTtpResultList(etlConfD,glass));
//                    }catch (Exception e){
//
//                    }
                }


                for (String key : etlGlassVMap.keySet()) {
                    String glassId = etlGlassVMap.get(key).get(0).getGlassId();
                    if ("CELL2".equals(etlConfD.getCellType())) glassId = etlGlassVMap.get(key).get(0).getChipId();

                    //清空Session表
                    try {
                        saveFileDataDao.deleteFile(etlConfD);
                    } catch (ETLException2 e) {
                        logger.error("{} 失败原因：{}", e.getErrorCode().getErrorMsg(), LoggerUtil.stackTraceToString(e));
                        if (org.springframework.util.StringUtils.isEmpty(errMsg)) {
                            errMsg = e.getErrorCode().getErrorMsg() + "错误原因：" + e.getErrMsg();
                        } else {
                            errMsg += e.getErrorCode().getErrorMsg() + "错误原因：" + e.getErrMsg();
                        }
                        continue;
                    }

                    //save and proc
                    try {
                        saveFileDataDao.saveFileData(etlConfD, etlGlassVMap.get(key), etlChipVMap.get(key), etlDefectVMap.get(key), etlGlassVMap.get(key).get(0).getGlassId());
                        logger.info("glassId={},opeId={},procEndTime={} 保存成功!", glassId, etlGlassVMap.get(key).get(0).getStepId(), sdf.format(etlGlassVMap.get(key).get(0).getGlassEndTime().getTime()));

                        okCnt++;
                    } catch (ETLException2 e) {
                        String glassMsg = "glassId=" + glassId
                                + ",opeId=" + etlGlassVMap.get(key).get(0).getStepId()
                                + ",procEndTime=" + sdf.format(etlGlassVMap.get(key).get(0).getGlassEndTime().getTime());
                        logger.error(ErrorCode.ERROR_PROCEDURE_ORA_DEFECT_FILE.getErrorMsg() + "\n" + glassMsg + "保存失败,错误原因：" + LoggerUtil.stackTraceToString(e));
                        errCnt++;
                        if (!StringUtils.isEmpty(errMsg)) {
                            errMsg = errMsg
                                    + "glassId=" + glassId
                                    + ",opeId=" + etlGlassVMap.get(key).get(0).getStepId()
                                    + ",procEndTime=" + sdf.format(etlGlassVMap.get(key).get(0).getGlassEndTime().getTime())
                                    + "保存失败,错误原因：" + e.getErrMsg() + "。\n";
                        } else {
                            errMsg = "glassId=" + glassId
                                    + ",opeId=" + etlGlassVMap.get(key).get(0).getStepId()
                                    + ",procEndTime=" + sdf.format(etlGlassVMap.get(key).get(0).getGlassEndTime().getTime())
                                    + "保存失败,错误原因：" + e.getErrMsg() + "。\n";
                        }
                    }
                }
            }
        } else {
            logger.info("没有此区间的数据。"); // todo print log & save etl data
        }
        resMsg[0] = String.valueOf(okCnt);
        resMsg[1] = String.valueOf(errCnt);
        resMsg[2] = errMsg;

        return resMsg;
    }


    public List<String> getDistinctOpes(EtlConfD etlConfD) {
        List<String> opes=loadDefectInfoService.getDistinctOpes(etlConfD);
        return opes;
    }
}
